package com.wencai;

import com.wencai.bean.*;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import okhttp3.*;
import com.wencai.util.CmdExecutor;
import com.wencai.util.ExchangeDay;

import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author wangpan
 * @date 2023/5/8
 */
public class WenCai {
    private static String url = "https://www.iwencai.com/customized/chart/get-robot-data";

    private static String hexin = "Hexin-V";
    private static String hexinValue = CmdExecutor.getToken();

    static {
        hexinValue = hexinValue.trim();
    }

    private static Map<String,String> messageMap = new HashMap<String,String>();

//    private static String cookie =
//"\n" +
//        "other_uid=Ths_iwencai_Xuangu_01aafs5bn4oveso6y4fy3glwt1xrpehb; ta_random_userid=bzz5hj6kgb; cid=f93f8bbc305adde2601b554eeee81ace1666768355; cid=f93f8bbc305adde2601b554eeee81ace1666768355; ComputerID=f93f8bbc305adde2601b554eeee81ace1666768355; WafStatus=0; v=A0-xUBJNd8cCGHO7Ya7DYLvL3uhcdKM6PcunimFX6jzFFWEWaUQz5k2YN8Jy";
//
//    static {
//        cookie = cookie.trim();
//    }


    private static String dir = "概念";
    private static String startTime = "0930";
    private static String endTime = "0935";
    private static String rangeType = "分时";

    private static String conceptDir = "D:\\Users\\Administrator\\Desktop\\记录\\" + dir + "\\";

    private static String industryDir = "D:\\Users\\Administrator\\Desktop\\记录\\行业\\";


    public static void main(String[] args) throws IOException, InterruptedException {
        getCurrentDayStock();
    }

    public static String getCurrentDayStock() throws IOException, InterruptedException {
        Date date = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");

        int hours = Calendar.getInstance().get(Calendar.HOUR_OF_DAY);
        int minutes = Calendar.getInstance().get(Calendar.MINUTE);
        boolean hasCurrentDayData = (hours == 9 && minutes > 36) || hours > 9;
        if(!hasCurrentDayData){
            Calendar cal = Calendar.getInstance();
            cal.add(Calendar.DATE, -1);
            date = cal.getTime();
        }

        String currentDate = sdf.format(date);
        if(messageMap.containsKey(currentDate)) {
            return messageMap.get(currentDate);
        }else{
            String s = queryWenCai(currentDate, currentDate, IndexType.concept);
            messageMap.put(currentDate, s);
            return s;
        }
    }

    private static String queryWenCai(String date, String currentDate, String indexType) throws IOException, InterruptedException {
        String dir;
        if (IndexType.concept.equals(indexType)) {
            dir = conceptDir;
        } else {
            dir = industryDir;
        }
//        date = ExchangeDay.getLatestExchangeDay(date);
        while (date.compareTo(currentDate) <= 0) {
            String filePath = dir + date + ".txt";
            if (new File(filePath).exists()) {
                date = ExchangeDay.getNextExchangeDay(date);
                continue;
            }
            String s = incrementStocks(date, startTime, endTime, indexType);
            System.out.println(date);
            System.out.println(s);
            return s;
//            if (!s.isEmpty()) {
//                IOUtils.writeFile(filePath, s);
//            }
//            date = ExchangeDay.getNextExchangeDay(date);
//            Thread.sleep(5000);
        }
        return null;
    }

    // date的格式: 20230509, startTime的格式: 0930, endTime的格式: 0935
    private static String incrementStocks(String date, String startTime, String endTime, String indexType) throws IOException {
        String rangeDate = date.replaceAll("(\\d{4})(\\d{2})(\\d{2})", "$1年$2月$3日");
        String rangeStartTime = startTime.replaceAll("(\\d{2})(\\d{2})", "$1点$2分");
        String rangeEndTime = endTime.replaceAll("(\\d{2})(\\d{2})", "$1点$2分");

        String time = rangeDate + rangeStartTime + "至" + rangeEndTime;

        String incrementStartTime = startTime.replaceAll("(\\d{2})(\\d{2})", "$1:$2:00");
        String incrementEndTime = endTime.replaceAll("(\\d{2})(\\d{2})", "$1:$2:00");
        String range = date + " " + incrementStartTime + "-" + date + " " + incrementEndTime;

        List<Index> morningIndex = getRangeIndex(time, indexType);
        StringBuilder sb = new StringBuilder();
        sb.append(date).append("\n");
        for (int i = 0; i < 3; i++) {
            if (morningIndex.size() - 1 < i) {
                continue;
            }
            Index index = morningIndex.get(i);
            List<Stock> dailyStock = getDailyStock(time, index.getName(), indexType, range);
            String indexIncrement = index.getIncrement();
            indexIncrement = BigDecimal.valueOf(Double.parseDouble(indexIncrement)).setScale(2, BigDecimal.ROUND_HALF_UP).toString();
            String indexName = index.getName().replaceAll("(_\\d+)","");

            sb.append(indexName).append("(").append(indexIncrement).append(")").append(": ").append(System.lineSeparator());
            int k = 3;
            if (dailyStock.size() < 3) {
                k = dailyStock.size();
            }
            for (int j = 0; j < k; j++) {
                String increment = dailyStock.get(j).getIncrement();
                increment = BigDecimal.valueOf(Double.parseDouble(increment)).setScale(2, BigDecimal.ROUND_HALF_UP).toString();
                String stockName = dailyStock.get(j).getName(); //.replaceAll("_s[h|z]\\.","");
                String stockCode = dailyStock.get(j).getCode().replaceAll("s[h|z]\\.","");
                sb.append(stockName).append("_").append(stockCode).append(" ").append(increment).append(System.lineSeparator());
            }
            sb.append("\n");
        }
        return sb.toString();
    }


// 分时涨跌幅:前复权[20230509 09:35]


    // 获取同花顺指数范围涨幅
    public static List<Index> getRangeIndex(String date, String indexType) throws IOException {
        OkHttpClient client = new OkHttpClient.Builder().build();
        RequestBody requestBody = RequestBody.create(JSON.toJSONString(new WencaiPayload(date + "涨幅排名;同花顺" + indexType + "指数;主板;非st;", SecondaryIntent.zhishu)), MediaType.get("application/json;charset=UTF-8"));
        Request request = new Request.Builder().url(url).method("post", requestBody).addHeader(hexin, hexinValue)
                .build();
        Call call = client.newCall(request);
        Response response = call.execute();
        if (response.code() != 200) {
            throw new RuntimeException();
        }
        String body = response.body().string();
        JSONArray datas = getDatas(body);
        List<Index> list = new ArrayList<>();
        for (Object obj : datas) {
            JSONObject js = (JSONObject) obj;
            String indexNameField = js.keySet().stream().filter(item -> item.matches("指数简称")).findFirst().orElse("");
            String indexCodeField = js.keySet().stream().filter(item -> item.matches("指数代码")).findFirst().orElse("");
            String indexName = js.get(indexNameField).toString();
            String indexCode = js.get(indexCodeField).toString();
            indexName = indexName + "_" + indexCode;
            String incrementFiled = js.keySet().stream().filter(item -> item.matches("指数@分时区间涨跌幅:不复权\\[.*?]")).findFirst().orElse("");
            BigDecimal indexIncrement = (BigDecimal) js.get(incrementFiled);
            // 特殊处理: 如果是送转填权, 则直接跳过
            if (indexName.equals("送转填权") || indexName.equals("注册制次新股")) {
                continue;
            }
            list.add(new Index(indexName, indexIncrement.toString()));
        }
        return list;
    }

    // 获取同花顺指数早盘涨幅(9点35分)
    public static List<Index> getAbsoluteIndex(String date, String indexType) throws IOException {
        OkHttpClient client = new OkHttpClient.Builder().build();
        RequestBody requestBody = RequestBody.create(JSON.toJSONString(new WencaiPayload(date + "涨幅排名;同花顺" + indexType + "指数;主板;非st;", SecondaryIntent.zhishu)), MediaType.get("application/json;charset=UTF-8"));
        Request request = new Request.Builder().url(url).method("post", requestBody).addHeader(hexin, hexinValue)
                .build();
        Call call = client.newCall(request);
        Response response = call.execute();
        if (response.code() != 200) {
            throw new RuntimeException();
        }
        String body = response.body().string();
        JSONArray datas = getDatas(body);
        List<Index> list = new ArrayList<>();
        for (Object obj : datas) {
            JSONObject js = (JSONObject) obj;
            String indexNameField = js.keySet().stream().filter(item -> item.matches("指数简称")).findFirst().orElse("");
            String indexName = js.get(indexNameField).toString();
            String incrementFiled = js.keySet().stream().filter(item -> item.matches("指数@分时涨跌幅:前复权\\[.*?]")).findFirst().orElse("");
            String indexIncrement = (String) js.get(incrementFiled);
            list.add(new Index(indexName, indexIncrement));
        }
        return list;
    }


    public static List<Stock> getDailyStock(String date, String indexName, String indexType, String range) throws IOException {
        OkHttpClient client = new OkHttpClient.Builder().build();
        RequestBody requestBody = RequestBody.create(JSON.toJSONString(new WencaiPayload("所属同花顺" + indexType + "是" + indexName + ";" + date + "分时区间涨幅排名;主板;非st;"

                , SecondaryIntent.stock)), MediaType.get("application/json;charset=UTF-8"));
        Request request = new Request.Builder().url(url).method("post", requestBody).addHeader(hexin, hexinValue)
                .build();
        Call call = client.newCall(request);
        Response response = call.execute();
        if (response.code() != 200) {
            throw new RuntimeException();
        }
        String body = response.body().string();
        JSONArray datas = getDatas(body);
        List<Stock> list = new ArrayList<>();

        for (Object obj : datas) {
            JSONObject js = (JSONObject) obj;
            String stockName = js.get("股票简称").toString();
            Number increment = (Number) js.get("分时区间涨跌幅:前复权[" + range + "]");
            String code = js.get("code").toString();
            if (code.startsWith("00")) {
                code = "sz." + code;
            } else {
                code = "sh." + code;
            }
            list.add(new Stock(stockName, code, increment.toString(), date));
        }
        return list;
    }


    // 获取同花顺指数日涨幅列表
    public static List<Index> getDailyIndexs(String date, String indexType) throws IOException {
        OkHttpClient client = new OkHttpClient.Builder().build();
        RequestBody requestBody = RequestBody.create(JSON.toJSONString(new WencaiPayload(date + "同花顺" + indexType + "涨幅排名;主板;非st;", SecondaryIntent.zhishu)), MediaType.get("application/json;charset=UTF-8"));
        Request request = new Request.Builder().url(url).method("post", requestBody).addHeader(hexin, hexinValue)
                .build();
        Call call = client.newCall(request);
        Response response = call.execute();
        if (response.code() != 200) {
            throw new RuntimeException();
        }
        String body = response.body().string();
        JSONArray datas = getDatas(body);
        List<Index> list = new ArrayList<>();
        for (Object obj : datas) {
            JSONObject js = (JSONObject) obj;
            String indexNameField = js.keySet().stream().filter(item -> item.matches("指数简称")).findFirst().orElse("");
            String indexName = js.get(indexNameField).toString();
            String incrementFiled = js.keySet().stream().filter(item -> item.matches("指数@涨跌幅:前复权\\[\\d+]")).findFirst().orElse("");
            BigDecimal indexIncrement = (BigDecimal) js.get(incrementFiled);
            list.add(new Index(indexName, indexIncrement.toString()));
        }
        return list;
    }

    private static JSONArray getDatas(String body) {
        JSONObject jsonObject = JSON.parseObject(body);
        Object statusCode = jsonObject.get("status_code");
        if (!Integer.valueOf(0).equals(statusCode)) {
            throw new RuntimeException();
        }
        JSONArray data = (JSONArray) ((JSONObject) jsonObject.get("data")).get("answer");
        JSONObject json = (JSONObject) data.get(0);
        JSONObject txt = (JSONObject) ((JSONArray) json.get("txt")).get(0);
        JSONObject content = (JSONObject) txt.get("content");
        JSONArray components = (JSONArray) content.get("components");
        for(Object componentObject: components){
            JSONObject component = (JSONObject) componentObject;
            if("container".equals(component.get("show_type"))){
                return (JSONArray) (((JSONObject)component.get("data")).get("datas"));
            }
        }
        throw new RuntimeException("未正确获取container");
    }
}
